use std::{
    ffi::{c_char, c_void, CString},
    fmt,
    rc::Rc,
};

use gl_context_loader::GenericGlContext;

// Ensure we can call dlopen/dlsym/dlclose
#[link(name = "dl")]
extern "C" {
    fn dlopen(filename: *const c_char, flag: i32) -> *mut c_void;
    fn dlsym(handle: *mut c_void, symbol: *const c_char) -> *mut c_void;
    fn dlclose(handle: *mut c_void) -> i32;
}

// Wrapper to get access to the GL function pointers
pub struct GlFunctions {
    /// The handle returned by dlopen.
    _opengl_lib_handle: *mut c_void,

    /// Actual GL function pointers (glClear, glClearColor, etc.)
    pub functions: Rc<GenericGlContext>,
}

impl fmt::Debug for GlFunctions {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // Just show the pointer’s numeric value
        write!(
            f,
            "GlFunctions {{ handle = {:0x?} }}",
            self._opengl_lib_handle as usize
        )
    }
}

impl GlFunctions {
    /// Allocates and loads the OpenGL function pointers via dlopen
    pub fn initialize() -> Result<Self, String> {
        fn get_func(symbol_name: &str, handle: *mut c_void) -> *mut gl_context_loader::c_void {
            let c_string = CString::new(symbol_name).unwrap();
            (unsafe { dlsym(handle, c_string.as_ptr()) }) as *mut _
        }

        // Typical flags for dlopen:
        const RTLD_NOW: i32 = 2;
        const RTLD_LOCAL: i32 = 0;
        const RTLD_GLOBAL: i32 = 8; // Or 0x100 if needed

        // Full path to Apple’s OpenGL framework library
        // Alternatively: "/System/Library/Frameworks/OpenGL.framework/OpenGL"
        let framework_path =
            CString::new("/System/Library/Frameworks/OpenGL.framework/OpenGL").unwrap();

        // RTLD_NOW means "resolve all symbols immediately".
        // RTLD_GLOBAL or RTLD_LOCAL depends on your use-case.
        let handle = unsafe { dlopen(framework_path.as_ptr(), RTLD_NOW | RTLD_GLOBAL) };
        if handle.is_null() {
            return Err("Could not dlopen OpenGL.framework/OpenGL".to_string());
        }

        // Zero-init the entire function table
        let context = GenericGlContext {
            glAccum: get_func("glAccum", handle),
            glActiveTexture: get_func("glActiveTexture", handle),
            glAlphaFunc: get_func("glAlphaFunc", handle),
            glAreTexturesResident: get_func("glAreTexturesResident", handle),
            glArrayElement: get_func("glArrayElement", handle),
            glAttachShader: get_func("glAttachShader", handle),
            glBegin: get_func("glBegin", handle),
            glBeginConditionalRender: get_func("glBeginConditionalRender", handle),
            glBeginQuery: get_func("glBeginQuery", handle),
            glBeginTransformFeedback: get_func("glBeginTransformFeedback", handle),
            glBindAttribLocation: get_func("glBindAttribLocation", handle),
            glBindBuffer: get_func("glBindBuffer", handle),
            glBindBufferBase: get_func("glBindBufferBase", handle),
            glBindBufferRange: get_func("glBindBufferRange", handle),
            glBindFragDataLocation: get_func("glBindFragDataLocation", handle),
            glBindFragDataLocationIndexed: get_func("glBindFragDataLocationIndexed", handle),
            glBindFramebuffer: get_func("glBindFramebuffer", handle),
            glBindRenderbuffer: get_func("glBindRenderbuffer", handle),
            glBindSampler: get_func("glBindSampler", handle),
            glBindTexture: get_func("glBindTexture", handle),
            glBindVertexArray: get_func("glBindVertexArray", handle),
            glBindVertexArrayAPPLE: get_func("glBindVertexArrayAPPLE", handle),
            glBitmap: get_func("glBitmap", handle),
            glBlendBarrierKHR: get_func("glBlendBarrierKHR", handle),
            glBlendColor: get_func("glBlendColor", handle),
            glBlendEquation: get_func("glBlendEquation", handle),
            glBlendEquationSeparate: get_func("glBlendEquationSeparate", handle),
            glBlendFunc: get_func("glBlendFunc", handle),
            glBlendFuncSeparate: get_func("glBlendFuncSeparate", handle),
            glBlitFramebuffer: get_func("glBlitFramebuffer", handle),
            glBufferData: get_func("glBufferData", handle),
            glBufferStorage: get_func("glBufferStorage", handle),
            glBufferSubData: get_func("glBufferSubData", handle),
            glCallList: get_func("glCallList", handle),
            glCallLists: get_func("glCallLists", handle),
            glCheckFramebufferStatus: get_func("glCheckFramebufferStatus", handle),
            glClampColor: get_func("glClampColor", handle),
            glClear: get_func("glClear", handle),
            glClearAccum: get_func("glClearAccum", handle),
            glClearBufferfi: get_func("glClearBufferfi", handle),
            glClearBufferfv: get_func("glClearBufferfv", handle),
            glClearBufferiv: get_func("glClearBufferiv", handle),
            glClearBufferuiv: get_func("glClearBufferuiv", handle),
            glClearColor: get_func("glClearColor", handle),
            glClearDepth: get_func("glClearDepth", handle),
            glClearIndex: get_func("glClearIndex", handle),
            glClearStencil: get_func("glClearStencil", handle),
            glClientActiveTexture: get_func("glClientActiveTexture", handle),
            glClientWaitSync: get_func("glClientWaitSync", handle),
            glClipPlane: get_func("glClipPlane", handle),
            glColor3b: get_func("glColor3b", handle),
            glColor3bv: get_func("glColor3bv", handle),
            glColor3d: get_func("glColor3d", handle),
            glColor3dv: get_func("glColor3dv", handle),
            glColor3f: get_func("glColor3f", handle),
            glColor3fv: get_func("glColor3fv", handle),
            glColor3i: get_func("glColor3i", handle),
            glColor3iv: get_func("glColor3iv", handle),
            glColor3s: get_func("glColor3s", handle),
            glColor3sv: get_func("glColor3sv", handle),
            glColor3ub: get_func("glColor3ub", handle),
            glColor3ubv: get_func("glColor3ubv", handle),
            glColor3ui: get_func("glColor3ui", handle),
            glColor3uiv: get_func("glColor3uiv", handle),
            glColor3us: get_func("glColor3us", handle),
            glColor3usv: get_func("glColor3usv", handle),
            glColor4b: get_func("glColor4b", handle),
            glColor4bv: get_func("glColor4bv", handle),
            glColor4d: get_func("glColor4d", handle),
            glColor4dv: get_func("glColor4dv", handle),
            glColor4f: get_func("glColor4f", handle),
            glColor4fv: get_func("glColor4fv", handle),
            glColor4i: get_func("glColor4i", handle),
            glColor4iv: get_func("glColor4iv", handle),
            glColor4s: get_func("glColor4s", handle),
            glColor4sv: get_func("glColor4sv", handle),
            glColor4ub: get_func("glColor4ub", handle),
            glColor4ubv: get_func("glColor4ubv", handle),
            glColor4ui: get_func("glColor4ui", handle),
            glColor4uiv: get_func("glColor4uiv", handle),
            glColor4us: get_func("glColor4us", handle),
            glColor4usv: get_func("glColor4usv", handle),
            glColorMask: get_func("glColorMask", handle),
            glColorMaski: get_func("glColorMaski", handle),
            glColorMaterial: get_func("glColorMaterial", handle),
            glColorP3ui: get_func("glColorP3ui", handle),
            glColorP3uiv: get_func("glColorP3uiv", handle),
            glColorP4ui: get_func("glColorP4ui", handle),
            glColorP4uiv: get_func("glColorP4uiv", handle),
            glColorPointer: get_func("glColorPointer", handle),
            glCompileShader: get_func("glCompileShader", handle),
            glCompressedTexImage1D: get_func("glCompressedTexImage1D", handle),
            glCompressedTexImage2D: get_func("glCompressedTexImage2D", handle),
            glCompressedTexImage3D: get_func("glCompressedTexImage3D", handle),
            glCompressedTexSubImage1D: get_func("glCompressedTexSubImage1D", handle),
            glCompressedTexSubImage2D: get_func("glCompressedTexSubImage2D", handle),
            glCompressedTexSubImage3D: get_func("glCompressedTexSubImage3D", handle),
            glCopyBufferSubData: get_func("glCopyBufferSubData", handle),
            glCopyImageSubData: get_func("glCopyImageSubData", handle),
            glCopyPixels: get_func("glCopyPixels", handle),
            glCopyTexImage1D: get_func("glCopyTexImage1D", handle),
            glCopyTexImage2D: get_func("glCopyTexImage2D", handle),
            glCopyTexSubImage1D: get_func("glCopyTexSubImage1D", handle),
            glCopyTexSubImage2D: get_func("glCopyTexSubImage2D", handle),
            glCopyTexSubImage3D: get_func("glCopyTexSubImage3D", handle),
            glCreateProgram: get_func("glCreateProgram", handle),
            glCreateShader: get_func("glCreateShader", handle),
            glCullFace: get_func("glCullFace", handle),
            glDebugMessageCallback: get_func("glDebugMessageCallback", handle),
            glDebugMessageCallbackKHR: get_func("glDebugMessageCallbackKHR", handle),
            glDebugMessageControl: get_func("glDebugMessageControl", handle),
            glDebugMessageControlKHR: get_func("glDebugMessageControlKHR", handle),
            glDebugMessageInsert: get_func("glDebugMessageInsert", handle),
            glDebugMessageInsertKHR: get_func("glDebugMessageInsertKHR", handle),
            glDeleteBuffers: get_func("glDeleteBuffers", handle),
            glDeleteFencesAPPLE: get_func("glDeleteFencesAPPLE", handle),
            glDeleteFramebuffers: get_func("glDeleteFramebuffers", handle),
            glDeleteLists: get_func("glDeleteLists", handle),
            glDeleteProgram: get_func("glDeleteProgram", handle),
            glDeleteQueries: get_func("glDeleteQueries", handle),
            glDeleteRenderbuffers: get_func("glDeleteRenderbuffers", handle),
            glDeleteSamplers: get_func("glDeleteSamplers", handle),
            glDeleteShader: get_func("glDeleteShader", handle),
            glDeleteSync: get_func("glDeleteSync", handle),
            glDeleteTextures: get_func("glDeleteTextures", handle),
            glDeleteVertexArrays: get_func("glDeleteVertexArrays", handle),
            glDeleteVertexArraysAPPLE: get_func("glDeleteVertexArraysAPPLE", handle),
            glDepthFunc: get_func("glDepthFunc", handle),
            glDepthMask: get_func("glDepthMask", handle),
            glDepthRange: get_func("glDepthRange", handle),
            glDetachShader: get_func("glDetachShader", handle),
            glDisable: get_func("glDisable", handle),
            glDisableClientState: get_func("glDisableClientState", handle),
            glDisableVertexAttribArray: get_func("glDisableVertexAttribArray", handle),
            glDisablei: get_func("glDisablei", handle),
            glDrawArrays: get_func("glDrawArrays", handle),
            glDrawArraysInstanced: get_func("glDrawArraysInstanced", handle),
            glDrawBuffer: get_func("glDrawBuffer", handle),
            glDrawBuffers: get_func("glDrawBuffers", handle),
            glDrawElements: get_func("glDrawElements", handle),
            glDrawElementsBaseVertex: get_func("glDrawElementsBaseVertex", handle),
            glDrawElementsInstanced: get_func("glDrawElementsInstanced", handle),
            glDrawElementsInstancedBaseVertex: get_func(
                "glDrawElementsInstancedBaseVertex",
                handle,
            ),
            glDrawPixels: get_func("glDrawPixels", handle),
            glDrawRangeElements: get_func("glDrawRangeElements", handle),
            glDrawRangeElementsBaseVertex: get_func("glDrawRangeElementsBaseVertex", handle),
            glEdgeFlag: get_func("glEdgeFlag", handle),
            glEdgeFlagPointer: get_func("glEdgeFlagPointer", handle),
            glEdgeFlagv: get_func("glEdgeFlagv", handle),
            glEnable: get_func("glEnable", handle),
            glEnableClientState: get_func("glEnableClientState", handle),
            glEnableVertexAttribArray: get_func("glEnableVertexAttribArray", handle),
            glEnablei: get_func("glEnablei", handle),
            glEnd: get_func("glEnd", handle),
            glEndConditionalRender: get_func("glEndConditionalRender", handle),
            glEndList: get_func("glEndList", handle),
            glEndQuery: get_func("glEndQuery", handle),
            glEndTransformFeedback: get_func("glEndTransformFeedback", handle),
            glEvalCoord1d: get_func("glEvalCoord1d", handle),
            glEvalCoord1dv: get_func("glEvalCoord1dv", handle),
            glEvalCoord1f: get_func("glEvalCoord1f", handle),
            glEvalCoord1fv: get_func("glEvalCoord1fv", handle),
            glEvalCoord2d: get_func("glEvalCoord2d", handle),
            glEvalCoord2dv: get_func("glEvalCoord2dv", handle),
            glEvalCoord2f: get_func("glEvalCoord2f", handle),
            glEvalCoord2fv: get_func("glEvalCoord2fv", handle),
            glEvalMesh1: get_func("glEvalMesh1", handle),
            glEvalMesh2: get_func("glEvalMesh2", handle),
            glEvalPoint1: get_func("glEvalPoint1", handle),
            glEvalPoint2: get_func("glEvalPoint2", handle),
            glFeedbackBuffer: get_func("glFeedbackBuffer", handle),
            glFenceSync: get_func("glFenceSync", handle),
            glFinish: get_func("glFinish", handle),
            glFinishFenceAPPLE: get_func("glFinishFenceAPPLE", handle),
            glFinishObjectAPPLE: get_func("glFinishObjectAPPLE", handle),
            glFlush: get_func("glFlush", handle),
            glFlushMappedBufferRange: get_func("glFlushMappedBufferRange", handle),
            glFogCoordPointer: get_func("glFogCoordPointer", handle),
            glFogCoordd: get_func("glFogCoordd", handle),
            glFogCoorddv: get_func("glFogCoorddv", handle),
            glFogCoordf: get_func("glFogCoordf", handle),
            glFogCoordfv: get_func("glFogCoordfv", handle),
            glFogf: get_func("glFogf", handle),
            glFogfv: get_func("glFogfv", handle),
            glFogi: get_func("glFogi", handle),
            glFogiv: get_func("glFogiv", handle),
            glFramebufferRenderbuffer: get_func("glFramebufferRenderbuffer", handle),
            glFramebufferTexture: get_func("glFramebufferTexture", handle),
            glFramebufferTexture1D: get_func("glFramebufferTexture1D", handle),
            glFramebufferTexture2D: get_func("glFramebufferTexture2D", handle),
            glFramebufferTexture3D: get_func("glFramebufferTexture3D", handle),
            glFramebufferTextureLayer: get_func("glFramebufferTextureLayer", handle),
            glFrontFace: get_func("glFrontFace", handle),
            glFrustum: get_func("glFrustum", handle),
            glGenBuffers: get_func("glGenBuffers", handle),
            glGenFencesAPPLE: get_func("glGenFencesAPPLE", handle),
            glGenFramebuffers: get_func("glGenFramebuffers", handle),
            glGenLists: get_func("glGenLists", handle),
            glGenQueries: get_func("glGenQueries", handle),
            glGenRenderbuffers: get_func("glGenRenderbuffers", handle),
            glGenSamplers: get_func("glGenSamplers", handle),
            glGenTextures: get_func("glGenTextures", handle),
            glGenVertexArrays: get_func("glGenVertexArrays", handle),
            glGenVertexArraysAPPLE: get_func("glGenVertexArraysAPPLE", handle),
            glGenerateMipmap: get_func("glGenerateMipmap", handle),
            glGetActiveAttrib: get_func("glGetActiveAttrib", handle),
            glGetActiveUniform: get_func("glGetActiveUniform", handle),
            glGetActiveUniformBlockName: get_func("glGetActiveUniformBlockName", handle),
            glGetActiveUniformBlockiv: get_func("glGetActiveUniformBlockiv", handle),
            glGetActiveUniformName: get_func("glGetActiveUniformName", handle),
            glGetActiveUniformsiv: get_func("glGetActiveUniformsiv", handle),
            glGetAttachedShaders: get_func("glGetAttachedShaders", handle),
            glGetAttribLocation: get_func("glGetAttribLocation", handle),
            glGetBooleani_v: get_func("glGetBooleani_v", handle),
            glGetBooleanv: get_func("glGetBooleanv", handle),
            glGetBufferParameteri64v: get_func("glGetBufferParameteri64v", handle),
            glGetBufferParameteriv: get_func("glGetBufferParameteriv", handle),
            glGetBufferPointerv: get_func("glGetBufferPointerv", handle),
            glGetBufferSubData: get_func("glGetBufferSubData", handle),
            glGetClipPlane: get_func("glGetClipPlane", handle),
            glGetCompressedTexImage: get_func("glGetCompressedTexImage", handle),
            glGetDebugMessageLog: get_func("glGetDebugMessageLog", handle),
            glGetDebugMessageLogKHR: get_func("glGetDebugMessageLogKHR", handle),
            glGetDoublev: get_func("glGetDoublev", handle),
            glGetError: get_func("glGetError", handle),
            glGetFloatv: get_func("glGetFloatv", handle),
            glGetFragDataIndex: get_func("glGetFragDataIndex", handle),
            glGetFragDataLocation: get_func("glGetFragDataLocation", handle),
            glGetFramebufferAttachmentParameteriv: get_func(
                "glGetFramebufferAttachmentParameteriv",
                handle,
            ),
            glGetInteger64i_v: get_func("glGetInteger64i_v", handle),
            glGetInteger64v: get_func("glGetInteger64v", handle),
            glGetIntegeri_v: get_func("glGetIntegeri_v", handle),
            glGetIntegerv: get_func("glGetIntegerv", handle),
            glGetLightfv: get_func("glGetLightfv", handle),
            glGetLightiv: get_func("glGetLightiv", handle),
            glGetMapdv: get_func("glGetMapdv", handle),
            glGetMapfv: get_func("glGetMapfv", handle),
            glGetMapiv: get_func("glGetMapiv", handle),
            glGetMaterialfv: get_func("glGetMaterialfv", handle),
            glGetMaterialiv: get_func("glGetMaterialiv", handle),
            glGetMultisamplefv: get_func("glGetMultisamplefv", handle),
            glGetObjectLabel: get_func("glGetObjectLabel", handle),
            glGetObjectLabelKHR: get_func("glGetObjectLabelKHR", handle),
            glGetObjectPtrLabel: get_func("glGetObjectPtrLabel", handle),
            glGetObjectPtrLabelKHR: get_func("glGetObjectPtrLabelKHR", handle),
            glGetPixelMapfv: get_func("glGetPixelMapfv", handle),
            glGetPixelMapuiv: get_func("glGetPixelMapuiv", handle),
            glGetPixelMapusv: get_func("glGetPixelMapusv", handle),
            glGetPointerv: get_func("glGetPointerv", handle),
            glGetPointervKHR: get_func("glGetPointervKHR", handle),
            glGetPolygonStipple: get_func("glGetPolygonStipple", handle),
            glGetProgramBinary: get_func("glGetProgramBinary", handle),
            glGetProgramInfoLog: get_func("glGetProgramInfoLog", handle),
            glGetProgramiv: get_func("glGetProgramiv", handle),
            glGetQueryObjecti64v: get_func("glGetQueryObjecti64v", handle),
            glGetQueryObjectiv: get_func("glGetQueryObjectiv", handle),
            glGetQueryObjectui64v: get_func("glGetQueryObjectui64v", handle),
            glGetQueryObjectuiv: get_func("glGetQueryObjectuiv", handle),
            glGetQueryiv: get_func("glGetQueryiv", handle),
            glGetRenderbufferParameteriv: get_func("glGetRenderbufferParameteriv", handle),
            glGetSamplerParameterIiv: get_func("glGetSamplerParameterIiv", handle),
            glGetSamplerParameterIuiv: get_func("glGetSamplerParameterIuiv", handle),
            glGetSamplerParameterfv: get_func("glGetSamplerParameterfv", handle),
            glGetSamplerParameteriv: get_func("glGetSamplerParameteriv", handle),
            glGetShaderInfoLog: get_func("glGetShaderInfoLog", handle),
            glGetShaderSource: get_func("glGetShaderSource", handle),
            glGetShaderiv: get_func("glGetShaderiv", handle),
            glGetString: get_func("glGetString", handle),
            glGetStringi: get_func("glGetStringi", handle),
            glGetSynciv: get_func("glGetSynciv", handle),
            glGetTexEnvfv: get_func("glGetTexEnvfv", handle),
            glGetTexEnviv: get_func("glGetTexEnviv", handle),
            glGetTexGendv: get_func("glGetTexGendv", handle),
            glGetTexGenfv: get_func("glGetTexGenfv", handle),
            glGetTexGeniv: get_func("glGetTexGeniv", handle),
            glGetTexImage: get_func("glGetTexImage", handle),
            glGetTexLevelParameterfv: get_func("glGetTexLevelParameterfv", handle),
            glGetTexLevelParameteriv: get_func("glGetTexLevelParameteriv", handle),
            glGetTexParameterIiv: get_func("glGetTexParameterIiv", handle),
            glGetTexParameterIuiv: get_func("glGetTexParameterIuiv", handle),
            glGetTexParameterPointervAPPLE: get_func("glGetTexParameterPointervAPPLE", handle),
            glGetTexParameterfv: get_func("glGetTexParameterfv", handle),
            glGetTexParameteriv: get_func("glGetTexParameteriv", handle),
            glGetTransformFeedbackVarying: get_func("glGetTransformFeedbackVarying", handle),
            glGetUniformBlockIndex: get_func("glGetUniformBlockIndex", handle),
            glGetUniformIndices: get_func("glGetUniformIndices", handle),
            glGetUniformLocation: get_func("glGetUniformLocation", handle),
            glGetUniformfv: get_func("glGetUniformfv", handle),
            glGetUniformiv: get_func("glGetUniformiv", handle),
            glGetUniformuiv: get_func("glGetUniformuiv", handle),
            glGetVertexAttribIiv: get_func("glGetVertexAttribIiv", handle),
            glGetVertexAttribIuiv: get_func("glGetVertexAttribIuiv", handle),
            glGetVertexAttribPointerv: get_func("glGetVertexAttribPointerv", handle),
            glGetVertexAttribdv: get_func("glGetVertexAttribdv", handle),
            glGetVertexAttribfv: get_func("glGetVertexAttribfv", handle),
            glGetVertexAttribiv: get_func("glGetVertexAttribiv", handle),
            glHint: get_func("glHint", handle),
            glIndexMask: get_func("glIndexMask", handle),
            glIndexPointer: get_func("glIndexPointer", handle),
            glIndexd: get_func("glIndexd", handle),
            glIndexdv: get_func("glIndexdv", handle),
            glIndexf: get_func("glIndexf", handle),
            glIndexfv: get_func("glIndexfv", handle),
            glIndexi: get_func("glIndexi", handle),
            glIndexiv: get_func("glIndexiv", handle),
            glIndexs: get_func("glIndexs", handle),
            glIndexsv: get_func("glIndexsv", handle),
            glIndexub: get_func("glIndexub", handle),
            glIndexubv: get_func("glIndexubv", handle),
            glInitNames: get_func("glInitNames", handle),
            glInsertEventMarkerEXT: get_func("glInsertEventMarkerEXT", handle),
            glInterleavedArrays: get_func("glInterleavedArrays", handle),
            glInvalidateBufferData: get_func("glInvalidateBufferData", handle),
            glInvalidateBufferSubData: get_func("glInvalidateBufferSubData", handle),
            glInvalidateFramebuffer: get_func("glInvalidateFramebuffer", handle),
            glInvalidateSubFramebuffer: get_func("glInvalidateSubFramebuffer", handle),
            glInvalidateTexImage: get_func("glInvalidateTexImage", handle),
            glInvalidateTexSubImage: get_func("glInvalidateTexSubImage", handle),
            glIsBuffer: get_func("glIsBuffer", handle),
            glIsEnabled: get_func("glIsEnabled", handle),
            glIsEnabledi: get_func("glIsEnabledi", handle),
            glIsFenceAPPLE: get_func("glIsFenceAPPLE", handle),
            glIsFramebuffer: get_func("glIsFramebuffer", handle),
            glIsList: get_func("glIsList", handle),
            glIsProgram: get_func("glIsProgram", handle),
            glIsQuery: get_func("glIsQuery", handle),
            glIsRenderbuffer: get_func("glIsRenderbuffer", handle),
            glIsSampler: get_func("glIsSampler", handle),
            glIsShader: get_func("glIsShader", handle),
            glIsSync: get_func("glIsSync", handle),
            glIsTexture: get_func("glIsTexture", handle),
            glIsVertexArray: get_func("glIsVertexArray", handle),
            glIsVertexArrayAPPLE: get_func("glIsVertexArrayAPPLE", handle),
            glLightModelf: get_func("glLightModelf", handle),
            glLightModelfv: get_func("glLightModelfv", handle),
            glLightModeli: get_func("glLightModeli", handle),
            glLightModeliv: get_func("glLightModeliv", handle),
            glLightf: get_func("glLightf", handle),
            glLightfv: get_func("glLightfv", handle),
            glLighti: get_func("glLighti", handle),
            glLightiv: get_func("glLightiv", handle),
            glLineStipple: get_func("glLineStipple", handle),
            glLineWidth: get_func("glLineWidth", handle),
            glLinkProgram: get_func("glLinkProgram", handle),
            glListBase: get_func("glListBase", handle),
            glLoadIdentity: get_func("glLoadIdentity", handle),
            glLoadMatrixd: get_func("glLoadMatrixd", handle),
            glLoadMatrixf: get_func("glLoadMatrixf", handle),
            glLoadName: get_func("glLoadName", handle),
            glLoadTransposeMatrixd: get_func("glLoadTransposeMatrixd", handle),
            glLoadTransposeMatrixf: get_func("glLoadTransposeMatrixf", handle),
            glLogicOp: get_func("glLogicOp", handle),
            glMap1d: get_func("glMap1d", handle),
            glMap1f: get_func("glMap1f", handle),
            glMap2d: get_func("glMap2d", handle),
            glMap2f: get_func("glMap2f", handle),
            glMapBuffer: get_func("glMapBuffer", handle),
            glMapBufferRange: get_func("glMapBufferRange", handle),
            glMapGrid1d: get_func("glMapGrid1d", handle),
            glMapGrid1f: get_func("glMapGrid1f", handle),
            glMapGrid2d: get_func("glMapGrid2d", handle),
            glMapGrid2f: get_func("glMapGrid2f", handle),
            glMaterialf: get_func("glMaterialf", handle),
            glMaterialfv: get_func("glMaterialfv", handle),
            glMateriali: get_func("glMateriali", handle),
            glMaterialiv: get_func("glMaterialiv", handle),
            glMatrixMode: get_func("glMatrixMode", handle),
            glMultMatrixd: get_func("glMultMatrixd", handle),
            glMultMatrixf: get_func("glMultMatrixf", handle),
            glMultTransposeMatrixd: get_func("glMultTransposeMatrixd", handle),
            glMultTransposeMatrixf: get_func("glMultTransposeMatrixf", handle),
            glMultiDrawArrays: get_func("glMultiDrawArrays", handle),
            glMultiDrawElements: get_func("glMultiDrawElements", handle),
            glMultiDrawElementsBaseVertex: get_func("glMultiDrawElementsBaseVertex", handle),
            glMultiTexCoord1d: get_func("glMultiTexCoord1d", handle),
            glMultiTexCoord1dv: get_func("glMultiTexCoord1dv", handle),
            glMultiTexCoord1f: get_func("glMultiTexCoord1f", handle),
            glMultiTexCoord1fv: get_func("glMultiTexCoord1fv", handle),
            glMultiTexCoord1i: get_func("glMultiTexCoord1i", handle),
            glMultiTexCoord1iv: get_func("glMultiTexCoord1iv", handle),
            glMultiTexCoord1s: get_func("glMultiTexCoord1s", handle),
            glMultiTexCoord1sv: get_func("glMultiTexCoord1sv", handle),
            glMultiTexCoord2d: get_func("glMultiTexCoord2d", handle),
            glMultiTexCoord2dv: get_func("glMultiTexCoord2dv", handle),
            glMultiTexCoord2f: get_func("glMultiTexCoord2f", handle),
            glMultiTexCoord2fv: get_func("glMultiTexCoord2fv", handle),
            glMultiTexCoord2i: get_func("glMultiTexCoord2i", handle),
            glMultiTexCoord2iv: get_func("glMultiTexCoord2iv", handle),
            glMultiTexCoord2s: get_func("glMultiTexCoord2s", handle),
            glMultiTexCoord2sv: get_func("glMultiTexCoord2sv", handle),
            glMultiTexCoord3d: get_func("glMultiTexCoord3d", handle),
            glMultiTexCoord3dv: get_func("glMultiTexCoord3dv", handle),
            glMultiTexCoord3f: get_func("glMultiTexCoord3f", handle),
            glMultiTexCoord3fv: get_func("glMultiTexCoord3fv", handle),
            glMultiTexCoord3i: get_func("glMultiTexCoord3i", handle),
            glMultiTexCoord3iv: get_func("glMultiTexCoord3iv", handle),
            glMultiTexCoord3s: get_func("glMultiTexCoord3s", handle),
            glMultiTexCoord3sv: get_func("glMultiTexCoord3sv", handle),
            glMultiTexCoord4d: get_func("glMultiTexCoord4d", handle),
            glMultiTexCoord4dv: get_func("glMultiTexCoord4dv", handle),
            glMultiTexCoord4f: get_func("glMultiTexCoord4f", handle),
            glMultiTexCoord4fv: get_func("glMultiTexCoord4fv", handle),
            glMultiTexCoord4i: get_func("glMultiTexCoord4i", handle),
            glMultiTexCoord4iv: get_func("glMultiTexCoord4iv", handle),
            glMultiTexCoord4s: get_func("glMultiTexCoord4s", handle),
            glMultiTexCoord4sv: get_func("glMultiTexCoord4sv", handle),
            glMultiTexCoordP1ui: get_func("glMultiTexCoordP1ui", handle),
            glMultiTexCoordP1uiv: get_func("glMultiTexCoordP1uiv", handle),
            glMultiTexCoordP2ui: get_func("glMultiTexCoordP2ui", handle),
            glMultiTexCoordP2uiv: get_func("glMultiTexCoordP2uiv", handle),
            glMultiTexCoordP3ui: get_func("glMultiTexCoordP3ui", handle),
            glMultiTexCoordP3uiv: get_func("glMultiTexCoordP3uiv", handle),
            glMultiTexCoordP4ui: get_func("glMultiTexCoordP4ui", handle),
            glMultiTexCoordP4uiv: get_func("glMultiTexCoordP4uiv", handle),
            glNewList: get_func("glNewList", handle),
            glNormal3b: get_func("glNormal3b", handle),
            glNormal3bv: get_func("glNormal3bv", handle),
            glNormal3d: get_func("glNormal3d", handle),
            glNormal3dv: get_func("glNormal3dv", handle),
            glNormal3f: get_func("glNormal3f", handle),
            glNormal3fv: get_func("glNormal3fv", handle),
            glNormal3i: get_func("glNormal3i", handle),
            glNormal3iv: get_func("glNormal3iv", handle),
            glNormal3s: get_func("glNormal3s", handle),
            glNormal3sv: get_func("glNormal3sv", handle),
            glNormalP3ui: get_func("glNormalP3ui", handle),
            glNormalP3uiv: get_func("glNormalP3uiv", handle),
            glNormalPointer: get_func("glNormalPointer", handle),
            glObjectLabel: get_func("glObjectLabel", handle),
            glObjectLabelKHR: get_func("glObjectLabelKHR", handle),
            glObjectPtrLabel: get_func("glObjectPtrLabel", handle),
            glObjectPtrLabelKHR: get_func("glObjectPtrLabelKHR", handle),
            glOrtho: get_func("glOrtho", handle),
            glPassThrough: get_func("glPassThrough", handle),
            glPixelMapfv: get_func("glPixelMapfv", handle),
            glPixelMapuiv: get_func("glPixelMapuiv", handle),
            glPixelMapusv: get_func("glPixelMapusv", handle),
            glPixelStoref: get_func("glPixelStoref", handle),
            glPixelStorei: get_func("glPixelStorei", handle),
            glPixelTransferf: get_func("glPixelTransferf", handle),
            glPixelTransferi: get_func("glPixelTransferi", handle),
            glPixelZoom: get_func("glPixelZoom", handle),
            glPointParameterf: get_func("glPointParameterf", handle),
            glPointParameterfv: get_func("glPointParameterfv", handle),
            glPointParameteri: get_func("glPointParameteri", handle),
            glPointParameteriv: get_func("glPointParameteriv", handle),
            glPointSize: get_func("glPointSize", handle),
            glPolygonMode: get_func("glPolygonMode", handle),
            glPolygonOffset: get_func("glPolygonOffset", handle),
            glPolygonStipple: get_func("glPolygonStipple", handle),
            glPopAttrib: get_func("glPopAttrib", handle),
            glPopClientAttrib: get_func("glPopClientAttrib", handle),
            glPopDebugGroup: get_func("glPopDebugGroup", handle),
            glPopDebugGroupKHR: get_func("glPopDebugGroupKHR", handle),
            glPopGroupMarkerEXT: get_func("glPopGroupMarkerEXT", handle),
            glPopMatrix: get_func("glPopMatrix", handle),
            glPopName: get_func("glPopName", handle),
            glPrimitiveRestartIndex: get_func("glPrimitiveRestartIndex", handle),
            glPrioritizeTextures: get_func("glPrioritizeTextures", handle),
            glProgramBinary: get_func("glProgramBinary", handle),
            glProgramParameteri: get_func("glProgramParameteri", handle),
            glProvokingVertex: get_func("glProvokingVertex", handle),
            glPushAttrib: get_func("glPushAttrib", handle),
            glPushClientAttrib: get_func("glPushClientAttrib", handle),
            glPushDebugGroup: get_func("glPushDebugGroup", handle),
            glPushDebugGroupKHR: get_func("glPushDebugGroupKHR", handle),
            glPushGroupMarkerEXT: get_func("glPushGroupMarkerEXT", handle),
            glPushMatrix: get_func("glPushMatrix", handle),
            glPushName: get_func("glPushName", handle),
            glQueryCounter: get_func("glQueryCounter", handle),
            glRasterPos2d: get_func("glRasterPos2d", handle),
            glRasterPos2dv: get_func("glRasterPos2dv", handle),
            glRasterPos2f: get_func("glRasterPos2f", handle),
            glRasterPos2fv: get_func("glRasterPos2fv", handle),
            glRasterPos2i: get_func("glRasterPos2i", handle),
            glRasterPos2iv: get_func("glRasterPos2iv", handle),
            glRasterPos2s: get_func("glRasterPos2s", handle),
            glRasterPos2sv: get_func("glRasterPos2sv", handle),
            glRasterPos3d: get_func("glRasterPos3d", handle),
            glRasterPos3dv: get_func("glRasterPos3dv", handle),
            glRasterPos3f: get_func("glRasterPos3f", handle),
            glRasterPos3fv: get_func("glRasterPos3fv", handle),
            glRasterPos3i: get_func("glRasterPos3i", handle),
            glRasterPos3iv: get_func("glRasterPos3iv", handle),
            glRasterPos3s: get_func("glRasterPos3s", handle),
            glRasterPos3sv: get_func("glRasterPos3sv", handle),
            glRasterPos4d: get_func("glRasterPos4d", handle),
            glRasterPos4dv: get_func("glRasterPos4dv", handle),
            glRasterPos4f: get_func("glRasterPos4f", handle),
            glRasterPos4fv: get_func("glRasterPos4fv", handle),
            glRasterPos4i: get_func("glRasterPos4i", handle),
            glRasterPos4iv: get_func("glRasterPos4iv", handle),
            glRasterPos4s: get_func("glRasterPos4s", handle),
            glRasterPos4sv: get_func("glRasterPos4sv", handle),
            glReadBuffer: get_func("glReadBuffer", handle),
            glReadPixels: get_func("glReadPixels", handle),
            glRectd: get_func("glRectd", handle),
            glRectdv: get_func("glRectdv", handle),
            glRectf: get_func("glRectf", handle),
            glRectfv: get_func("glRectfv", handle),
            glRecti: get_func("glRecti", handle),
            glRectiv: get_func("glRectiv", handle),
            glRects: get_func("glRects", handle),
            glRectsv: get_func("glRectsv", handle),
            glRenderMode: get_func("glRenderMode", handle),
            glRenderbufferStorage: get_func("glRenderbufferStorage", handle),
            glRenderbufferStorageMultisample: get_func("glRenderbufferStorageMultisample", handle),
            glRotated: get_func("glRotated", handle),
            glRotatef: get_func("glRotatef", handle),
            glSampleCoverage: get_func("glSampleCoverage", handle),
            glSampleMaski: get_func("glSampleMaski", handle),
            glSamplerParameterIiv: get_func("glSamplerParameterIiv", handle),
            glSamplerParameterIuiv: get_func("glSamplerParameterIuiv", handle),
            glSamplerParameterf: get_func("glSamplerParameterf", handle),
            glSamplerParameterfv: get_func("glSamplerParameterfv", handle),
            glSamplerParameteri: get_func("glSamplerParameteri", handle),
            glSamplerParameteriv: get_func("glSamplerParameteriv", handle),
            glScaled: get_func("glScaled", handle),
            glScalef: get_func("glScalef", handle),
            glScissor: get_func("glScissor", handle),
            glSecondaryColor3b: get_func("glSecondaryColor3b", handle),
            glSecondaryColor3bv: get_func("glSecondaryColor3bv", handle),
            glSecondaryColor3d: get_func("glSecondaryColor3d", handle),
            glSecondaryColor3dv: get_func("glSecondaryColor3dv", handle),
            glSecondaryColor3f: get_func("glSecondaryColor3f", handle),
            glSecondaryColor3fv: get_func("glSecondaryColor3fv", handle),
            glSecondaryColor3i: get_func("glSecondaryColor3i", handle),
            glSecondaryColor3iv: get_func("glSecondaryColor3iv", handle),
            glSecondaryColor3s: get_func("glSecondaryColor3s", handle),
            glSecondaryColor3sv: get_func("glSecondaryColor3sv", handle),
            glSecondaryColor3ub: get_func("glSecondaryColor3ub", handle),
            glSecondaryColor3ubv: get_func("glSecondaryColor3ubv", handle),
            glSecondaryColor3ui: get_func("glSecondaryColor3ui", handle),
            glSecondaryColor3uiv: get_func("glSecondaryColor3uiv", handle),
            glSecondaryColor3us: get_func("glSecondaryColor3us", handle),
            glSecondaryColor3usv: get_func("glSecondaryColor3usv", handle),
            glSecondaryColorP3ui: get_func("glSecondaryColorP3ui", handle),
            glSecondaryColorP3uiv: get_func("glSecondaryColorP3uiv", handle),
            glSecondaryColorPointer: get_func("glSecondaryColorPointer", handle),
            glSelectBuffer: get_func("glSelectBuffer", handle),
            glSetFenceAPPLE: get_func("glSetFenceAPPLE", handle),
            glShadeModel: get_func("glShadeModel", handle),
            glShaderSource: get_func("glShaderSource", handle),
            glShaderStorageBlockBinding: get_func("glShaderStorageBlockBinding", handle),
            glStencilFunc: get_func("glStencilFunc", handle),
            glStencilFuncSeparate: get_func("glStencilFuncSeparate", handle),
            glStencilMask: get_func("glStencilMask", handle),
            glStencilMaskSeparate: get_func("glStencilMaskSeparate", handle),
            glStencilOp: get_func("glStencilOp", handle),
            glStencilOpSeparate: get_func("glStencilOpSeparate", handle),
            glTestFenceAPPLE: get_func("glTestFenceAPPLE", handle),
            glTestObjectAPPLE: get_func("glTestObjectAPPLE", handle),
            glTexBuffer: get_func("glTexBuffer", handle),
            glTexCoord1d: get_func("glTexCoord1d", handle),
            glTexCoord1dv: get_func("glTexCoord1dv", handle),
            glTexCoord1f: get_func("glTexCoord1f", handle),
            glTexCoord1fv: get_func("glTexCoord1fv", handle),
            glTexCoord1i: get_func("glTexCoord1i", handle),
            glTexCoord1iv: get_func("glTexCoord1iv", handle),
            glTexCoord1s: get_func("glTexCoord1s", handle),
            glTexCoord1sv: get_func("glTexCoord1sv", handle),
            glTexCoord2d: get_func("glTexCoord2d", handle),
            glTexCoord2dv: get_func("glTexCoord2dv", handle),
            glTexCoord2f: get_func("glTexCoord2f", handle),
            glTexCoord2fv: get_func("glTexCoord2fv", handle),
            glTexCoord2i: get_func("glTexCoord2i", handle),
            glTexCoord2iv: get_func("glTexCoord2iv", handle),
            glTexCoord2s: get_func("glTexCoord2s", handle),
            glTexCoord2sv: get_func("glTexCoord2sv", handle),
            glTexCoord3d: get_func("glTexCoord3d", handle),
            glTexCoord3dv: get_func("glTexCoord3dv", handle),
            glTexCoord3f: get_func("glTexCoord3f", handle),
            glTexCoord3fv: get_func("glTexCoord3fv", handle),
            glTexCoord3i: get_func("glTexCoord3i", handle),
            glTexCoord3iv: get_func("glTexCoord3iv", handle),
            glTexCoord3s: get_func("glTexCoord3s", handle),
            glTexCoord3sv: get_func("glTexCoord3sv", handle),
            glTexCoord4d: get_func("glTexCoord4d", handle),
            glTexCoord4dv: get_func("glTexCoord4dv", handle),
            glTexCoord4f: get_func("glTexCoord4f", handle),
            glTexCoord4fv: get_func("glTexCoord4fv", handle),
            glTexCoord4i: get_func("glTexCoord4i", handle),
            glTexCoord4iv: get_func("glTexCoord4iv", handle),
            glTexCoord4s: get_func("glTexCoord4s", handle),
            glTexCoord4sv: get_func("glTexCoord4sv", handle),
            glTexCoordP1ui: get_func("glTexCoordP1ui", handle),
            glTexCoordP1uiv: get_func("glTexCoordP1uiv", handle),
            glTexCoordP2ui: get_func("glTexCoordP2ui", handle),
            glTexCoordP2uiv: get_func("glTexCoordP2uiv", handle),
            glTexCoordP3ui: get_func("glTexCoordP3ui", handle),
            glTexCoordP3uiv: get_func("glTexCoordP3uiv", handle),
            glTexCoordP4ui: get_func("glTexCoordP4ui", handle),
            glTexCoordP4uiv: get_func("glTexCoordP4uiv", handle),
            glTexCoordPointer: get_func("glTexCoordPointer", handle),
            glTexEnvf: get_func("glTexEnvf", handle),
            glTexEnvfv: get_func("glTexEnvfv", handle),
            glTexEnvi: get_func("glTexEnvi", handle),
            glTexEnviv: get_func("glTexEnviv", handle),
            glTexGend: get_func("glTexGend", handle),
            glTexGendv: get_func("glTexGendv", handle),
            glTexGenf: get_func("glTexGenf", handle),
            glTexGenfv: get_func("glTexGenfv", handle),
            glTexGeni: get_func("glTexGeni", handle),
            glTexGeniv: get_func("glTexGeniv", handle),
            glTexImage1D: get_func("glTexImage1D", handle),
            glTexImage2D: get_func("glTexImage2D", handle),
            glTexImage2DMultisample: get_func("glTexImage2DMultisample", handle),
            glTexImage3D: get_func("glTexImage3D", handle),
            glTexImage3DMultisample: get_func("glTexImage3DMultisample", handle),
            glTexParameterIiv: get_func("glTexParameterIiv", handle),
            glTexParameterIuiv: get_func("glTexParameterIuiv", handle),
            glTexParameterf: get_func("glTexParameterf", handle),
            glTexParameterfv: get_func("glTexParameterfv", handle),
            glTexParameteri: get_func("glTexParameteri", handle),
            glTexParameteriv: get_func("glTexParameteriv", handle),
            glTexStorage1D: get_func("glTexStorage1D", handle),
            glTexStorage2D: get_func("glTexStorage2D", handle),
            glTexStorage3D: get_func("glTexStorage3D", handle),
            glTexSubImage1D: get_func("glTexSubImage1D", handle),
            glTexSubImage2D: get_func("glTexSubImage2D", handle),
            glTexSubImage3D: get_func("glTexSubImage3D", handle),
            glTextureRangeAPPLE: get_func("glTextureRangeAPPLE", handle),
            glTransformFeedbackVaryings: get_func("glTransformFeedbackVaryings", handle),
            glTranslated: get_func("glTranslated", handle),
            glTranslatef: get_func("glTranslatef", handle),
            glUniform1f: get_func("glUniform1f", handle),
            glUniform1fv: get_func("glUniform1fv", handle),
            glUniform1i: get_func("glUniform1i", handle),
            glUniform1iv: get_func("glUniform1iv", handle),
            glUniform1ui: get_func("glUniform1ui", handle),
            glUniform1uiv: get_func("glUniform1uiv", handle),
            glUniform2f: get_func("glUniform2f", handle),
            glUniform2fv: get_func("glUniform2fv", handle),
            glUniform2i: get_func("glUniform2i", handle),
            glUniform2iv: get_func("glUniform2iv", handle),
            glUniform2ui: get_func("glUniform2ui", handle),
            glUniform2uiv: get_func("glUniform2uiv", handle),
            glUniform3f: get_func("glUniform3f", handle),
            glUniform3fv: get_func("glUniform3fv", handle),
            glUniform3i: get_func("glUniform3i", handle),
            glUniform3iv: get_func("glUniform3iv", handle),
            glUniform3ui: get_func("glUniform3ui", handle),
            glUniform3uiv: get_func("glUniform3uiv", handle),
            glUniform4f: get_func("glUniform4f", handle),
            glUniform4fv: get_func("glUniform4fv", handle),
            glUniform4i: get_func("glUniform4i", handle),
            glUniform4iv: get_func("glUniform4iv", handle),
            glUniform4ui: get_func("glUniform4ui", handle),
            glUniform4uiv: get_func("glUniform4uiv", handle),
            glUniformBlockBinding: get_func("glUniformBlockBinding", handle),
            glUniformMatrix2fv: get_func("glUniformMatrix2fv", handle),
            glUniformMatrix2x3fv: get_func("glUniformMatrix2x3fv", handle),
            glUniformMatrix2x4fv: get_func("glUniformMatrix2x4fv", handle),
            glUniformMatrix3fv: get_func("glUniformMatrix3fv", handle),
            glUniformMatrix3x2fv: get_func("glUniformMatrix3x2fv", handle),
            glUniformMatrix3x4fv: get_func("glUniformMatrix3x4fv", handle),
            glUniformMatrix4fv: get_func("glUniformMatrix4fv", handle),
            glUniformMatrix4x2fv: get_func("glUniformMatrix4x2fv", handle),
            glUniformMatrix4x3fv: get_func("glUniformMatrix4x3fv", handle),
            glUnmapBuffer: get_func("glUnmapBuffer", handle),
            glUseProgram: get_func("glUseProgram", handle),
            glValidateProgram: get_func("glValidateProgram", handle),
            glVertex2d: get_func("glVertex2d", handle),
            glVertex2dv: get_func("glVertex2dv", handle),
            glVertex2f: get_func("glVertex2f", handle),
            glVertex2fv: get_func("glVertex2fv", handle),
            glVertex2i: get_func("glVertex2i", handle),
            glVertex2iv: get_func("glVertex2iv", handle),
            glVertex2s: get_func("glVertex2s", handle),
            glVertex2sv: get_func("glVertex2sv", handle),
            glVertex3d: get_func("glVertex3d", handle),
            glVertex3dv: get_func("glVertex3dv", handle),
            glVertex3f: get_func("glVertex3f", handle),
            glVertex3fv: get_func("glVertex3fv", handle),
            glVertex3i: get_func("glVertex3i", handle),
            glVertex3iv: get_func("glVertex3iv", handle),
            glVertex3s: get_func("glVertex3s", handle),
            glVertex3sv: get_func("glVertex3sv", handle),
            glVertex4d: get_func("glVertex4d", handle),
            glVertex4dv: get_func("glVertex4dv", handle),
            glVertex4f: get_func("glVertex4f", handle),
            glVertex4fv: get_func("glVertex4fv", handle),
            glVertex4i: get_func("glVertex4i", handle),
            glVertex4iv: get_func("glVertex4iv", handle),
            glVertex4s: get_func("glVertex4s", handle),
            glVertex4sv: get_func("glVertex4sv", handle),
            glVertexAttrib1d: get_func("glVertexAttrib1d", handle),
            glVertexAttrib1dv: get_func("glVertexAttrib1dv", handle),
            glVertexAttrib1f: get_func("glVertexAttrib1f", handle),
            glVertexAttrib1fv: get_func("glVertexAttrib1fv", handle),
            glVertexAttrib1s: get_func("glVertexAttrib1s", handle),
            glVertexAttrib1sv: get_func("glVertexAttrib1sv", handle),
            glVertexAttrib2d: get_func("glVertexAttrib2d", handle),
            glVertexAttrib2dv: get_func("glVertexAttrib2dv", handle),
            glVertexAttrib2f: get_func("glVertexAttrib2f", handle),
            glVertexAttrib2fv: get_func("glVertexAttrib2fv", handle),
            glVertexAttrib2s: get_func("glVertexAttrib2s", handle),
            glVertexAttrib2sv: get_func("glVertexAttrib2sv", handle),
            glVertexAttrib3d: get_func("glVertexAttrib3d", handle),
            glVertexAttrib3dv: get_func("glVertexAttrib3dv", handle),
            glVertexAttrib3f: get_func("glVertexAttrib3f", handle),
            glVertexAttrib3fv: get_func("glVertexAttrib3fv", handle),
            glVertexAttrib3s: get_func("glVertexAttrib3s", handle),
            glVertexAttrib3sv: get_func("glVertexAttrib3sv", handle),
            glVertexAttrib4Nbv: get_func("glVertexAttrib4Nbv", handle),
            glVertexAttrib4Niv: get_func("glVertexAttrib4Niv", handle),
            glVertexAttrib4Nsv: get_func("glVertexAttrib4Nsv", handle),
            glVertexAttrib4Nub: get_func("glVertexAttrib4Nub", handle),
            glVertexAttrib4Nubv: get_func("glVertexAttrib4Nubv", handle),
            glVertexAttrib4Nuiv: get_func("glVertexAttrib4Nuiv", handle),
            glVertexAttrib4Nusv: get_func("glVertexAttrib4Nusv", handle),
            glVertexAttrib4bv: get_func("glVertexAttrib4bv", handle),
            glVertexAttrib4d: get_func("glVertexAttrib4d", handle),
            glVertexAttrib4dv: get_func("glVertexAttrib4dv", handle),
            glVertexAttrib4f: get_func("glVertexAttrib4f", handle),
            glVertexAttrib4fv: get_func("glVertexAttrib4fv", handle),
            glVertexAttrib4iv: get_func("glVertexAttrib4iv", handle),
            glVertexAttrib4s: get_func("glVertexAttrib4s", handle),
            glVertexAttrib4sv: get_func("glVertexAttrib4sv", handle),
            glVertexAttrib4ubv: get_func("glVertexAttrib4ubv", handle),
            glVertexAttrib4uiv: get_func("glVertexAttrib4uiv", handle),
            glVertexAttrib4usv: get_func("glVertexAttrib4usv", handle),
            glVertexAttribDivisor: get_func("glVertexAttribDivisor", handle),
            glVertexAttribI1i: get_func("glVertexAttribI1i", handle),
            glVertexAttribI1iv: get_func("glVertexAttribI1iv", handle),
            glVertexAttribI1ui: get_func("glVertexAttribI1ui", handle),
            glVertexAttribI1uiv: get_func("glVertexAttribI1uiv", handle),
            glVertexAttribI2i: get_func("glVertexAttribI2i", handle),
            glVertexAttribI2iv: get_func("glVertexAttribI2iv", handle),
            glVertexAttribI2ui: get_func("glVertexAttribI2ui", handle),
            glVertexAttribI2uiv: get_func("glVertexAttribI2uiv", handle),
            glVertexAttribI3i: get_func("glVertexAttribI3i", handle),
            glVertexAttribI3iv: get_func("glVertexAttribI3iv", handle),
            glVertexAttribI3ui: get_func("glVertexAttribI3ui", handle),
            glVertexAttribI3uiv: get_func("glVertexAttribI3uiv", handle),
            glVertexAttribI4bv: get_func("glVertexAttribI4bv", handle),
            glVertexAttribI4i: get_func("glVertexAttribI4i", handle),
            glVertexAttribI4iv: get_func("glVertexAttribI4iv", handle),
            glVertexAttribI4sv: get_func("glVertexAttribI4sv", handle),
            glVertexAttribI4ubv: get_func("glVertexAttribI4ubv", handle),
            glVertexAttribI4ui: get_func("glVertexAttribI4ui", handle),
            glVertexAttribI4uiv: get_func("glVertexAttribI4uiv", handle),
            glVertexAttribI4usv: get_func("glVertexAttribI4usv", handle),
            glVertexAttribIPointer: get_func("glVertexAttribIPointer", handle),
            glVertexAttribP1ui: get_func("glVertexAttribP1ui", handle),
            glVertexAttribP1uiv: get_func("glVertexAttribP1uiv", handle),
            glVertexAttribP2ui: get_func("glVertexAttribP2ui", handle),
            glVertexAttribP2uiv: get_func("glVertexAttribP2uiv", handle),
            glVertexAttribP3ui: get_func("glVertexAttribP3ui", handle),
            glVertexAttribP3uiv: get_func("glVertexAttribP3uiv", handle),
            glVertexAttribP4ui: get_func("glVertexAttribP4ui", handle),
            glVertexAttribP4uiv: get_func("glVertexAttribP4uiv", handle),
            glVertexAttribPointer: get_func("glVertexAttribPointer", handle),
            glVertexP2ui: get_func("glVertexP2ui", handle),
            glVertexP2uiv: get_func("glVertexP2uiv", handle),
            glVertexP3ui: get_func("glVertexP3ui", handle),
            glVertexP3uiv: get_func("glVertexP3uiv", handle),
            glVertexP4ui: get_func("glVertexP4ui", handle),
            glVertexP4uiv: get_func("glVertexP4uiv", handle),
            glVertexPointer: get_func("glVertexPointer", handle),
            glViewport: get_func("glViewport", handle),
            glWaitSync: get_func("glWaitSync", handle),
            glWindowPos2d: get_func("glWindowPos2d", handle),
            glWindowPos2dv: get_func("glWindowPos2dv", handle),
            glWindowPos2f: get_func("glWindowPos2f", handle),
            glWindowPos2fv: get_func("glWindowPos2fv", handle),
            glWindowPos2i: get_func("glWindowPos2i", handle),
            glWindowPos2iv: get_func("glWindowPos2iv", handle),
            glWindowPos2s: get_func("glWindowPos2s", handle),
            glWindowPos2sv: get_func("glWindowPos2sv", handle),
            glWindowPos3d: get_func("glWindowPos3d", handle),
            glWindowPos3dv: get_func("glWindowPos3dv", handle),
            glWindowPos3f: get_func("glWindowPos3f", handle),
            glWindowPos3fv: get_func("glWindowPos3fv", handle),
            glWindowPos3i: get_func("glWindowPos3i", handle),
            glWindowPos3iv: get_func("glWindowPos3iv", handle),
            glWindowPos3s: get_func("glWindowPos3s", handle),
            glWindowPos3sv: get_func("glWindowPos3sv", handle),
            glStartTilingQCOM: get_func("glStartTilingQCOM", handle),
            glEndTilingQCOM: get_func("glEndTilingQCOM", handle),
        };

        Ok(Self {
            _opengl_lib_handle: handle,
            functions: Rc::new(context),
        })
    }

    /// Returns the loaded function pointers (for use in your GL code).
    pub fn get_context(&self) -> Rc<GenericGlContext> {
        self.functions.clone()
    }
}

impl Drop for GlFunctions {
    fn drop(&mut self) {
        // On drop, close the handle.
        if !self._opengl_lib_handle.is_null() {
            unsafe {
                dlclose(self._opengl_lib_handle);
            }
        }
    }
}
